package emulator.shell.GUI.menu;

import java.awt.FileDialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;

import javax.swing.ButtonGroup;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import emulator.util.AddressRange;
import emulator.util.file.FileHelper;
import emulator.util.file.FileInfo;

@SuppressWarnings("serial")
public class MemoryFileDialog extends JDialog implements ActionListener {
	private int file_format;
	private boolean result_valid;
	private boolean is_save_dialog;
	private JTextField file_name_field;
	private JTextField start_address_field;
	private JTextField block_size_field;
	private HashMap<Integer, JRadioButton> select_file_format = new HashMap<Integer, JRadioButton>();
	private JCheckBox relink_basic_button;
	private boolean relink_basic;
	
	MemoryFileDialog(JFrame parent, String title, boolean is_save_dialog)
	{
		super(parent, title, true);
		this.is_save_dialog = is_save_dialog;
		buildContents();
		pack();
		setLocationRelativeTo(null); 
		result_valid = false;
		relink_basic = false;
		file_format = FileHelper.FILE_FORMAT_PRG;
		setFormatButton();
	}
	
	public boolean isResultValid() { return result_valid; }
	public String getFileName() { return file_name_field.getText();	}
	public int getStartAddress() { return fetchNumberFromField(start_address_field); }
	public int getBlockSize() {	return fetchNumberFromField(block_size_field); }
	public int getFileFormat() { return file_format; }
	public boolean getRelinkBasic() { return relink_basic; }
	
	public void setStartAddress(int start_address) {
		setNumberToField(start_address_field, start_address);
	}

	public void setBlockSize(int block_size) {
		setNumberToField(block_size_field, block_size);
	}

	private void buildContents() {
		JLabel label1 = new JLabel("Memory File");
		file_name_field = new JTextField();
		
		JLabel label2 = new JLabel("Start Address");
		start_address_field = new JTextField();
		
		JLabel label3 = new JLabel("Block Size");
		block_size_field = new JTextField();
		
		JButton file_button = createCommandButton("Browse...", "browse");
		JButton ok_button = createCommandButton("OK", "ok");
		JButton cancel_button = createCommandButton("Cancel", "cancel");
		
		JSeparator format_top = new JSeparator(JSeparator.HORIZONTAL);
		JSeparator format_bot = new JSeparator(JSeparator.HORIZONTAL);
		
		JRadioButton select_format_raw = createFormatSelectButton("Raw data", "select_raw", FileHelper.FILE_FORMAT_RAW, true);
		JRadioButton select_format_prg = createFormatSelectButton("Address as header (.prg)", "select_prg", FileHelper.FILE_FORMAT_PRG, true);
		JRadioButton select_format_p00 = createFormatSelectButton("PC64 format (.P00)", "select_p00", FileHelper.FILE_FORMAT_P00, !is_save_dialog);
		JRadioButton select_format_s20 = createFormatSelectButton("Phau Zeh saved session (.s20)", "select_s20", FileHelper.FILE_FORMAT_S20, false);
		JRadioButton select_format_pcv = createFormatSelectButton("PCVIC system snapshot (.pcv)", "select_pcvic", FileHelper.FILE_FORMAT_PCV, !is_save_dialog);
		JRadioButton select_format_crt = createFormatSelectButton("CCS64 cartridge image (.crt)", "select_crt", FileHelper.FILE_FORMAT_CRT, false);
		JRadioButton select_format_sid = createFormatSelectButton("SID file (.sid)", "select_sid", FileHelper.FILE_FORMAT_SID, !is_save_dialog);
		
		setFormatButton();
		
		ButtonGroup select_format_group = new ButtonGroup();
		select_format_group.add(select_format_raw);
		select_format_group.add(select_format_prg);
		select_format_group.add(select_format_p00);
		select_format_group.add(select_format_s20);
		select_format_group.add(select_format_pcv);
		select_format_group.add(select_format_crt);
		select_format_group.add(select_format_sid);

		relink_basic_button = new JCheckBox("BASIC");
		relink_basic_button.setSelected(relink_basic);
		relink_basic_button.setEnabled(!is_save_dialog);
		
		GroupLayout layout = new GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		
		layout.setAutoCreateGaps(true);
		layout.setAutoCreateContainerGaps(true);
		
	    layout.setHorizontalGroup(
	      layout.createParallelGroup(GroupLayout.Alignment.CENTER)
	        .addGroup(layout.createSequentialGroup()
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
	        		  .addComponent(label1)
	        		  .addComponent(label2)
	        		  .addComponent(label3)
	        		 )
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
	        		  .addComponent(file_name_field)
	        		  .addComponent(start_address_field)
	        		  .addComponent(block_size_field)
	        		 )
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
	        		  .addComponent(file_button)
	           		  .addComponent(relink_basic_button)
	        		 )
	          )
	      .addComponent(format_top)
          .addGroup(layout.createSequentialGroup()
    	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
    	        		  .addComponent(select_format_prg)
    	        		  .addComponent(select_format_s20)
    	        		  .addComponent(select_format_pcv)
    	           		  .addComponent(select_format_crt)
    	        		 )
    	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
    	        		  .addComponent(select_format_raw)
    	        		  .addComponent(select_format_p00)
    	        		  .addComponent(select_format_sid)
    	        		 )
        		  )
          .addComponent(format_bot)
   		  .addGroup(layout.createSequentialGroup()
   				  .addComponent(ok_button)
   				  .addComponent(cancel_button)
   				  )
	    );
	    layout.setVerticalGroup(
	       layout.createSequentialGroup()
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
    	               .addComponent(label1)
    	               .addComponent(file_name_field)
    	               .addComponent(file_button)
    	               )
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
    	               .addComponent(label2)
    	               .addComponent(start_address_field)
    	               .addComponent(relink_basic_button)
    	               )
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
    	               .addComponent(label3)
    	               .addComponent(block_size_field)
    	               )
    	      .addComponent(format_top)
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
	           		  .addComponent(select_format_prg)
	           		  .addComponent(select_format_raw)
    	               )
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
	           		  .addComponent(select_format_s20)
	           		  .addComponent(select_format_p00)
    	               )
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
	           		  .addComponent(select_format_pcv)
	           		  .addComponent(select_format_sid)
    	               )
       		  .addComponent(select_format_crt)
    	      .addComponent(format_bot)
	          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
    	               .addComponent(ok_button)
    	               .addComponent(cancel_button)
    	               )
	    );
	    layout.linkSize(SwingConstants.HORIZONTAL, ok_button, cancel_button);
	}

	private void setFormatButton() {
		JRadioButton button = select_file_format.get(file_format);
		if (button != null)
			button.setSelected(true);
	}

	private JRadioButton createFormatSelectButton(String caption, String command, int format, boolean enabled) {
		JRadioButton select_format_button = new JRadioButton(caption);
		select_format_button.setActionCommand(command);
		select_format_button.addActionListener(this);
		select_format_button.setEnabled(enabled);
		select_file_format.put(format, select_format_button);
		return select_format_button;
	}

	private JButton createCommandButton(String caption, String command) {
		JButton file_button = new JButton(caption);
		file_button.setActionCommand(command);
		file_button.addActionListener(this);
		return file_button;
	}

	private Integer fetchNumberFromField(JTextField number_field) {
		int number = -1;
		try {
			String num_text = number_field.getText();
			number = AddressRange.addressFromString(num_text);
		}
		catch (NumberFormatException e)	{ }
		return number;
	}

	private void setNumberToField(JTextField number_field,
								  Integer start_address)
	{
		number_field.setText(start_address < 0 ? "" : start_address.toString());
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if ("browse".equals(e.getActionCommand())) {
			onBrowse();
		} else if ("ok".equals(e.getActionCommand())) {
			onOk();
		} else if ("cancel".equals(e.getActionCommand())) {
			onCancel();
		} else if ("select_raw".equals(e.getActionCommand())) {
			onSelectRaw();
		} else if ("select_prg".equals(e.getActionCommand())) {
			onSelectPrg();
		} else if ("select_p00".equals(e.getActionCommand())) {
			onSelectP00();
		} else if ("select_s20".equals(e.getActionCommand())) {
			onSelectS20();
		} else if ("select_pcvic".equals(e.getActionCommand())) {
			onSelectPcVic();
		} else if ("select_crt".equals(e.getActionCommand())) {
			onSelectCrt();
		} else if ("select_sid".equals(e.getActionCommand())) {
			onSelectSid();
		}
	}

	private void selectFileFormat(int new_format) {
		file_format = new_format;
		String file_name = getFileName();
		if (!is_save_dialog && new_format != FileHelper.FILE_FORMAT_UNKNOWN && file_name != null)
		{
			FileInfo info = FileHelper.getFileInfo(file_name, file_format);
			if (info != null)
			{
				setStartAddress(info.getStartAddress());
				setBlockSize(info.getBlockSize());
			}
			else
			{
				setStartAddress(-1);
				setBlockSize(-1);
			}
			setFormatButton();
		}
	}

	private void onSelectRaw() {
		selectFileFormat(FileHelper.FILE_FORMAT_RAW);
	}

	private void onSelectPrg() {
		selectFileFormat(FileHelper.FILE_FORMAT_PRG);
	}

	private void onSelectP00() {
		selectFileFormat(FileHelper.FILE_FORMAT_P00);
	}

	private void onSelectS20() {
		selectFileFormat(FileHelper.FILE_FORMAT_S20);
	}

	private void onSelectPcVic() {
		selectFileFormat(FileHelper.FILE_FORMAT_PCV);
	}

	private void onSelectCrt() {
		selectFileFormat(FileHelper.FILE_FORMAT_CRT);
	}
	
	private void onSelectSid() {
		selectFileFormat(FileHelper.FILE_FORMAT_SID);
	}
	
	private void onCancel() {
		this.setVisible(false);
	}

	private void onOk() {
		relink_basic = relink_basic_button.isSelected();
		result_valid = true;
		this.setVisible(false);
	}

	private void onBrowse() {
		FileDialog fd = null;
		if (is_save_dialog)
		{
	        fd = new FileDialog(this, "Save Memory to File", FileDialog.SAVE);
		}
		else
		{
			fd = new FileDialog(this, "Load Memory from File", FileDialog.LOAD);
		}
		fd.setVisible(true);
		if (fd.getDirectory() != null && fd.getFile() != null)
		{
			String selected_file = fd.getDirectory() + fd.getFile();
			if (!selected_file.isEmpty())
			{
				file_name_field.setText(selected_file);
				int file_format = FileHelper.guessFileFormat(selected_file);
				selectFileFormat(file_format);
				if (file_format != FileHelper.FILE_FORMAT_UNKNOWN)
					setFormatButton();
			}
		}
	}
}
